﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using DiamondDesktop.Presenters;
using DiamondDesktop.Model;
using DiamondDesktop.type;


namespace DiamondDesktop.Presenters
{
    class FileDatabase : DiamondDesktop.Presenters.IDatabase
    {

        private string dirPath;   //数据文件夹路径

        private IFormatter formatter = new BinaryFormatter();

        public FileDatabase(string dirPath)
        {
            this.dirPath = dirPath;
        }

        //调用该方法前需进行检查，start要小于end
        /**
         * 载入一段时间的所有任务
         */
        public IList<Task> getPeriodTasks(DateTime start, DateTime end)
        {
            DateTime d1 = start.Date;
            DateTime d2 = end.Date;
            IList<Task> tasks = new List<Task>();
            DaySchedule schedule;
            do
            {
                schedule = getSchedule(d1);
                if (schedule != null)
                {
                    foreach (Task t in schedule.getTasks())
                        tasks.Add(t);
                }
                d1 = d1.AddDays(1);
            } while (d1 <= d2);

            return tasks;
        }

        /**
         * 载入某一天的任务
         */
        public IList<Task> getDaySchedule(DateTime date)
        {
            DaySchedule schedule = getSchedule(date);
            if (schedule == null)
                return new List<Task>();
            return schedule.getTasks();
        }

        /**
         * 根据上次的登录情况载入今天的任务
         */
        public IList<Task> getTodaySchedule(DateTime last, DateTime today)
        {
            DateTime d1 = last.Date;
            DateTime d2 = today.Date;
            IList<Task> tasks = getDaySchedule(today);
            DaySchedule schedule;
            while (d1 < d2)
            {
                schedule = getSchedule(d1);
                if (schedule != null)
                {
                    foreach (Task t in schedule.getTasks())
                    {
                        if (t.getStatus() == Status.UNFINISHED)
                        {
                            t.regenerateId();
                            tasks.Add(t);
                        }
                    }
                }
                d1 = d1.AddDays(1);
            }
            return tasks;
        }

        /**
        * 保存一条添加的任务
        */
        public bool saveTask(Task task)
        {
            DateTime date = new DateTime(task.getTaskId());
            string path = checkdir(date.Year, date.Month);
            if (path == null)
                return false;
            string fileName = Utility.makeFileName(date);
            path += "/" + fileName + Config.POSTFIX;
            DaySchedule schedule = getSchedule(date);
            if (schedule == null)
            {
                schedule = new DaySchedule(date.Date);
                IList<Task> l = new List<Task>();
                l.Add(task);
                schedule.setTasks(l);
            }
            else
            {
                schedule.getTasks().Add(task);
            }

            try
            {
                Stream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
                formatter.Serialize(stream, schedule);
                stream.Close();
            }
            catch
            {
                return false;
            }
            return true;
        }

        /**
         * 修改一条任务
         */
        public bool modifyTask(Task task)
        {
            DateTime date = new DateTime(task.getTaskId());
            string fileName = Utility.makeFileName(date);
            DaySchedule schedule = getSchedule(date);
            if (schedule != null)
            {
                IList<Task> tasks = schedule.getTasks();
                for (int i = 0; i < tasks.Count; i++)
                {
                    if (tasks.ElementAt(i).getTaskId() == task.getTaskId())
                    {
                        tasks.RemoveAt(i);
                        tasks.Insert(i, task);
                    }
                }
            }
            try
            {
                string path = dirPath + "/" + date.Year + "/" + date.Month + "/" + fileName + Config.POSTFIX;
                Stream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
                formatter.Serialize(stream, schedule);
                stream.Close();
            }
            catch
            {
                return false;
            }

            return true;
        }

        /**
         * 删除一条任务
         */
        public bool deleteTask(Task task)
        {
            DateTime date = new DateTime(task.getTaskId());
            string fileName = Utility.makeFileName(date);
            DaySchedule schedule = getSchedule(date);
            if (schedule != null)
            {
                for (int i = 0; i < schedule.getTasks().Count; i++)
                {
                    if (schedule.getTasks().ElementAt(i).getTaskId() == task.getTaskId())
                        schedule.getTasks().RemoveAt(i);
                }
            }
            string path = dirPath + "/" + date.Year + "/" + date.Month + "/" + fileName + Config.POSTFIX;
            try
            {
                Stream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
                formatter.Serialize(stream, schedule);
                stream.Close();
            }
            catch
            {
                return false;
            }

            return true;
        }


        public bool storeTasks(IList<Task> tasks, DateTime d)
        {
            string path = checkdir(d.Year, d.Month);
            if (path == null)
                return false;

            string fileName = Utility.makeFileName(d);
            path += "/" + fileName + Config.POSTFIX;

            DaySchedule schedule = new DaySchedule(d);
            schedule.setTasks(tasks);
            try
            {
                Stream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
                formatter.Serialize(stream, schedule);
                stream.Close();
            }
            catch
            {
                return false;
            }
            return true;
        }

        private DaySchedule getSchedule(DateTime date)
        {
            string fileName = Utility.makeFileName(date);
            string path = dirPath + "/" + date.Year + "/" + date.Month + "/" + fileName + Config.POSTFIX;
            DaySchedule schedule;
            try
            {
                Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
                schedule = (DaySchedule)formatter.Deserialize(stream);
                stream.Close();
            }
            catch
            {
                return null;
            }
            return schedule;
        }


        /*
         *检查文件夹是否存在，如果不存在则创建文件夹。
         *@return:存储某日数据文件的路径
         */
        private string checkdir(int year, int month)
        {
            string path;
            try
            {
                path = dirPath + "/" + year;
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);
                path += "/" + month;
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);
            }
            catch
            {
                return null;
            }
            return path;
        }

        public void setPath(string path)
        {
            this.dirPath = path;
        }

    }
}
